<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Streamgraph</title>
    <link rel="stylesheet" type="text/css" href="../../css/styles.css"/>
    <script type="text/javascript" src="../../lib/d3.js"></script>

    <style>
        path.area{
            fill-opacity: 1;
        }

        g.x path.domain{
            stroke: none;
        }

        g.x g.tick line{
            stroke: none;
        }
    </style>
</head>

<body>

<script type="text/javascript">
function streamgraph() {
    var _chart = {};

    var _width = 900, _height = 450,
            _margins = {top: 30, left: 30, right: 30, bottom: 80},
            _x, _y,
            _data = [],
            _colors = d3.scaleOrdinal(d3.schemeCategory10),
            _svg,
            _bodyG;

    _chart.render = function () {
        if (!_svg) {
            _svg = d3.select("body").append("svg")
                    .attr("height", _height)
                    .attr("width", _width);

            renderAxes(_svg);

            defineBodyClip(_svg);
        }

        renderBody(_svg);
    };

    function renderAxes(svg) {
        var axesG = svg.append("g")
                .attr("class", "axes");

        renderXAxis(axesG);

        renderYAxis(axesG);
    }

    function renderXAxis(axesG) {
        var xAxis = d3.axisBottom()
                .scale(_x.range([0, quadrantWidth()]));

        axesG.append("g")
                .attr("class", "x axis")
                .attr("transform", function () {
                    return "translate(" + xStart() + "," + (yStart() + 50) + ")";
                })
                .call(xAxis);
    }

    function renderYAxis(axesG) {
        _y.range([quadrantHeight() , 0]);
    }

    function defineBodyClip(svg) {
        var padding = 5;

        svg.append("defs")
                .append("clipPath")
                .attr("id", "body-clip")
                .append("rect")
                .attr("x", 0 - padding)
                .attr("y", 0)
                .attr("width", quadrantWidth() + 2 * padding)
                .attr("height", quadrantHeight());
    }

    function renderBody(svg) {
        if (!_bodyG)
            _bodyG = svg.append("g")
                    .attr("class", "body")
                    .attr("transform", "translate("
                            + xStart() + ","
                            + yEnd() + ")")
                    .attr("clip-path", "url(#body-clip)");

        var stack = d3.stack()
                .keys(['value1',
                    'value2',
                    'value3',
                    'value4',
                    'value5',
                    'value6',
                    'value7',
                    'value8'
                ])
                .order(d3.stackOrderInsideOut)
                .offset(d3.stackOffsetWiggle);

        var series = stack(_data);

        renderAreas(series);
    }

    function renderAreas(series) {
        var area = d3.area()
                .curve(d3.curveCardinal)
                .x(function (d, i) {
                    return _x(i);
                })
                .y0(function(d){return _y(d[0]);})
                .y1(function (d) {
                    return _y(d[1]);
                });

        var areaPaths = _bodyG.selectAll("path.area")
                .data(series);

        areaPaths.enter()
                .append("path")
            .merge(areaPaths)
                .style("fill", function (d, i) {
                    return _colors(Math.random());
                })
                .attr("class", "area")
            .transition()
                .attr("d", function (d) {
                    return area(d);
                });
    }

    function xStart() {
        return _margins.left;
    }

    function yStart() {
        return _height - _margins.bottom;
    }

    function xEnd() {
        return _width - _margins.right;
    }

    function yEnd() {
        return _margins.top;
    }

    function quadrantWidth() {
        return _width - _margins.left - _margins.right;
    }

    function quadrantHeight() {
        return _height - _margins.top - _margins.bottom;
    }

    _chart.width = function (w) {
        if (!arguments.length) return _width;
        _width = w;
        return _chart;
    };

    _chart.height = function (h) { 
        if (!arguments.length) return _height;
        _height = h;
        return _chart;
    };

    _chart.margins = function (m) {
        if (!arguments.length) return _margins;
        _margins = m;
        return _chart;
    };

    _chart.colors = function (c) {
        if (!arguments.length) return _colors;
        _colors = c;
        return _chart;
    };

    _chart.x = function (x) {
        if (!arguments.length) return _x;
        _x = x;
        return _chart;
    };

    _chart.y = function (y) {
        if (!arguments.length) return _y;
        _y = y;
        return _chart;
    };

    _chart.data = function (data) {
        if (!arguments.length) return _data;
        _data = data;
        return _chart;
    };

    return _chart;
}

function randomData() {
    return Math.random() * 10;
}

function update() {
    data = d3.range(numberOfDataPoint).map(function (i) {
        return {value1: randomData(),
            value2: randomData(),
            value3: randomData(),
            value4: randomData(),
            value5: randomData(),
            value6: randomData(),
            value7: randomData(),
            value8: randomData()
        };
    });

    chart.data(data).render();
}

var numberOfDataPoint = 51,
        data = [];

var chart = streamgraph()
        .x(d3.scaleLinear().domain([0, numberOfDataPoint - 1]))
        .y(d3.scaleLinear().domain([-30, 100]))
        .colors(d3.scaleLinear().range(["#aad", "#556"]));

update();
</script>

<div class="control-group">
    <button onclick="update()">Update</button>
</div>

</body>

</html>